﻿using Microsoft.IdentityModel.Logging;
using Newtonsoft.Json;
using System.IO.Ports;
using System.Net.Http.Headers;
using System.Net.Sockets;
using System.Net;
using System.Runtime.InteropServices;
using System.Text;
using System.Timers;
using IntelligentGateway.SmartCommunity.Model;
using IntelligentGateway.SmartCommunity.BUS;
using Timer = System.Timers.Timer;
using IntelligentGateway.Services;
using System.Drawing;
using IntelligentGateway.Model;
using IntelligentGateway.Data;
using IntelligentGateway.Model.Platform;
using System.Reflection;
using System.Linq;
using NuGet.Configuration;

namespace IntelligentGateway.SmartCommunity.DevicePlatform
{
    public class CEMSDeviceSerialData
    {
        public List<int> phy_list = new List<int>();//物理楼层列表
        public List<string> show_list = new List<string>();//显示楼层列表
        public List<int> act_list = new List<int>();//实际楼层列表
        public int OutboundInterval;//1楼门口机外呼延迟时间
        public int HeartCheck;//是否启用心跳检查
        public int MachineOutbound;//-1楼门口机外呼延迟时间
        public int IndoorOutbound;//室内机外呼延迟时间
        public int CarInOutbound;//轿厢内授权有效时间
        public int MachineAuthorize;//门口机授权有效时间
        public int IndoorAuthorize;//室内机授权有效时间
        public static Dictionary<int, ElevatorState> elevators_state = new Dictionary<int, ElevatorState>();//电梯状态

        public static Dictionary<int, DateTime> face_status = new Dictionary<int, DateTime>();//人脸设备状态接收最后时间
        public static List<CEMS_Cmd> cEMS_Cmds = new List<CEMS_Cmd>();//CEMS命令队列

        public static Dictionary<int, DateTime> manager_card = new Dictionary<int, DateTime>();//管理卡失效时间

        public static CancellationTokenSource tokenSource = new CancellationTokenSource();
        public CancellationToken token = tokenSource.Token;
        public ManualResetEvent resetEvent = new ManualResetEvent(true);

        public static CancellationTokenSource clear_tokenSource = new CancellationTokenSource();
        public CancellationToken clear_token = clear_tokenSource.Token;
        public ManualResetEvent clear_resetEvent = new ManualResetEvent(true);

        #region 人脸设备
        private static Socket ServerSocket;
        private static byte[] buffer;
        public async void Face_Start(int port)
        {
            TcpServerHelper tcpServerHelper = new TcpServerHelper(port);
            tcpServerHelper.Listen();
        }

        /// <summary>
        /// 开始监听
        /// </summary>
        public static void ServerListen()
        {
            Socket ts = ServerSocket.Accept();
            buffer = new byte[1024];
            ts.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Accept), ts);
        }
        /// <summary>
        /// 接收信息
        /// </summary>
        /// <param name="result"></param>
        public static void Accept(IAsyncResult result)
        {
            Socket ts = (Socket)result.AsyncState;
            int length = ts.EndReceive(result);
            result.AsyncWaitHandle.Close();

            //判断是否断开了，如果断开了，就不接收新数据了
            if (length > 0)
            {
                byte[] data = buffer.Skip(0).Take(length).ToArray();
                SmartCommunityLogHelper.Log("人脸识别:" + ToHexs(data));
                //清空数据，重新开始异步接收
                buffer = new byte[buffer.Length];
                ts.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(Accept), ts);
            }
            else
            {
                //断开的话，重新监听是否有新客户端连接过来
                ServerListen();
            }
        }

        /// <summary>
        /// TCP服务端
        /// </summary>
        public class TcpServerHelper : IDisposable
        {
            /// <summary>
            /// 监听套间字
            /// </summary>
            private Socket SocketS { get; set; }
            /// <summary>
            /// 连接池数列
            /// </summary>
            private List<Socket> SocketClients { get; set; }
            /// <summary>
            /// 连接数
            /// </summary>
            public int ConnectCount { get { return SocketClients.Count; } }
            /// <summary>
            /// 是否监听
            /// </summary>
            public bool isListening { get { return SocketS.IsBound; } }
            /// <summary>
            /// 监听的IP
            /// </summary>
            private string Ip { get; set; }
            /// <summary>
            /// 监听的端口
            /// </summary>
            private int Port { get; set; }
            /// <summary>
            /// 监听每次读取字节数
            /// </summary>
            private byte[] Buffer_data { get; set; }
            /// <summary>
            /// 最大连接数
            /// </summary>
            private int Count { get; set; }
            /// <summary>
            /// 接收消息
            /// </summary>
            public event Action<byte[], int, EndPoint> SocketReceive;
            /// <summary>
            /// 报错事件
            /// </summary>
            public event Action<string, Exception, EndPoint> SocketMessage;
            /// <summary>
            /// 连接事件
            /// </summary>
            public event Action<bool, EndPoint> ConnectEndPoints;
            /// <summary>
            /// /// <summary>
            /// 构造函数
            /// </summary>
            /// <param name="ip">监听的IP</param>
            /// <param name="port">监听的端口</param>
            /// <param name="bufferLength">监听每次读取字节数,默认1MB = 1024 * 1024B</param>
            public TcpServerHelper(int port, int bufferLength = 1024 * 1024, int count = int.MaxValue)
            {
                Port = port;
                Buffer_data = new byte[bufferLength];
                SocketClients = new List<Socket>();
                Count = count;
            }
            /// <summary>
            /// 开始监听
            /// </summary>
            /// <returns></returns>
            public async Task Listen()
            {
                try
                {
                    //1.0 实例化套接字(IP4寻找协议,流式协议,TCP协议)
                    SocketS = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    //3.0 创建网络端口,包括ip和端口
                    IPEndPoint endPoint = new IPEndPoint(IPAddress.Any, Port);
                    //4.0 绑定套接字
                    SocketS.Bind(endPoint);
                    //5.0 设置最大连接数
                    SocketS.Listen(Count);
                    //6.0 循环遍历连接
                    await Task.Run(() =>
                    {
                        for (; ; )
                        {
                            try
                            {
                                //接收客户端连接
                                Socket SocketClient = SocketS.Accept();
                                //加入连接池数列
                                SocketClients.Add(SocketClient);
                                //连接事件
                                SmartCommunityLogHelper.Log("设备连接");
                                //SocketMessage?.Invoke($"{SocketClient.RemoteEndPoint}接入", null, SocketClient.RemoteEndPoint);
                                ConnectEndPoints?.Invoke(true, SocketClient.RemoteEndPoint);
                                //开始监听
                                Thread thread = new Thread(Receive);
                                thread.Start(SocketClient);
                            }
                            catch (SocketException ex)
                            {
                                //SocketMessage?.Invoke("服务监听出错", ex, null);
                            }
                            catch (Exception ex)
                            {
                                //LogHelper.GetInstance().WriteLogEx(ex);
                            }
                        }
                    });
                }
                catch (Exception ex)
                {
                    //SocketMessage?.Invoke("服务监听出错", ex, null);
                }
            }

            /// <summary>
            /// 接收消息
            /// </summary>
            /// <param name="socket">来自客户端的socket</param>
            private void Receive(object SocketClient)
            {
                Socket socketClient = (Socket)SocketClient;
                try
                {
                    for (; ; )
                    {
                        //接收的字节数，当客户端下线时，receiveNumber=0
                        int receiveNumber = socketClient.Receive(Buffer_data);

                        //判断客户端是否下线，防止客户端下线时，服务端一直接收空消息
                        if (receiveNumber == 0)
                        {
                            throw new SocketException();
                        }
                        else if (receiveNumber > 0)
                        {
                            try
                            {
                                byte[] data = Buffer_data.Skip(0).Take(receiveNumber).ToArray();
                                DataSaveLogHelper.Log(ToHexs(data));
                                for (int i = 0; i < data.Length; i++)
                                {
                                    if (data[i] == 0x00 && data[i + 1] == 0x8B && data[i + 2] == 0x00 && data[i + 3] == 0x00 && data[i + 4] == 0x00)
                                    {
                                        int data_num = data[i + 5];
                                        byte[] bytes = new byte[data_num];
                                        for (int k = 0; k < data_num; k++)
                                        {
                                            bytes[k] = data[i + k + 6];
                                        }

                                        //梯号
                                        int ladder_id = bytes[0];
                                        if (face_status.ContainsKey(ladder_id))
                                        {
                                            face_status.Remove(ladder_id);
                                        }
                                        face_status.Add(ladder_id, DateTime.Now);

                                        //内呼类型 1=授权；2=点亮
                                        int type = 1;

                                        //门类型 1=前门；2=后门
                                        int door = 1;

                                        //开始地址
                                        byte[] add = new byte[2];
                                        add[0] = bytes[2];
                                        add[1] = bytes[3];

                                        int add_int = ByteToInt(add);
                                        //地址长度
                                        byte[] add_length = new byte[2];
                                        add_length[0] = bytes[4];
                                        add_length[1] = bytes[5];

                                        int add_length_int = ByteToInt(add_length);

                                        string data_floor = string.Empty;

                                        if (add_int >= 15 && add_int < 35)
                                        {
                                            if (add_int >= 15 && add_int < 20)
                                            {
                                                type = 1;
                                                door = 1;
                                                data_floor = FaceDataProcess(add_int, add_length_int, bytes, 15);
                                            }
                                            else if (add_int >= 20 && add_int < 25)
                                            {
                                                type = 1;
                                                door = 2;
                                                data_floor = FaceDataProcess(add_int, add_length_int, bytes, 20);
                                            }
                                            else if (add_int >= 25 && add_int < 30)
                                            {
                                                type = 2;
                                                door = 1;
                                                data_floor = FaceDataProcess(add_int, add_length_int, bytes, 25);
                                            }
                                            else if (add_int >= 30 && add_int < 35)
                                            {
                                                type = 2;
                                                door = 2;
                                                data_floor = FaceDataProcess(add_int, add_length_int, bytes, 30);
                                            }

                                            CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                            cEMS_Cmd.DeviceId = ladder_id;
                                            cEMS_Cmd.InBoundPFloorIds = data_floor;
                                            cEMS_Cmd.InBoundType = door == 1 ? 0 : 3;
                                            cEMS_Cmd.IsAuthorize = type;
                                            cEMS_Cmd.AuthorizeType = 1;
                                            SendInbound(cEMS_Cmd);

                                        }
                                        else if (add_int == 55)
                                        {
                                            //开放所有权限
                                            int qx_value = bytes[8];

                                            if (qx_value == 1)
                                            {
                                                ElevatorState elevatorState = new ElevatorState();
                                                if (elevators_state.TryGetValue(ladder_id, out elevatorState))
                                                {
                                                    if (elevatorState.Tk == 1)
                                                    {
                                                        if (manager_card.ContainsKey(ladder_id))
                                                        {
                                                            manager_card.Remove(ladder_id);
                                                        }
                                                        manager_card.Add(ladder_id, DateTime.Now);
                                                        //进入梯控，默认120秒 到时间进入梯控
                                                        IGTCPServerMessageProcess.SmartDisableLiftControl(ladder_id);
                                                    }
                                                }
                                            }
                                        }
                                        else if (add_int == 56)
                                        {
                                            //梯控
                                            int tk_value = bytes[8];
                                            if (tk_value == 1)
                                            {
                                                //进入梯控
                                                IGTCPServerMessageProcess.SmartEnableLiftControl(ladder_id);
                                            }
                                            else if (tk_value == 0)
                                            {
                                                //退出梯控
                                                IGTCPServerMessageProcess.SmartDisableLiftControl(ladder_id);
                                            }
                                        }


                                    }
                                }
                            }
                            catch
                            {

                            }

                        }

                        //接收成功事件
                        //SocketReceive(Buffer, receiveNumber, socketClient.RemoteEndPoint);
                    }
                }
                catch (SocketException ex)
                {
                    CloseConnect(socketClient, ex);
                }
                catch (Exception)
                {
                }
            }
            /// <summary>
            /// 断开连接
            /// </summary>
            /// <param name="socket"></param>
            /// <param name="ex"></param>
            private void CloseConnect(Socket socket, SocketException ex)
            {
                //SocketMessage?.Invoke($"{socket.RemoteEndPoint}断开连接", ex, socket.RemoteEndPoint);
                SmartCommunityLogHelper.Log("设备断开");
                ConnectEndPoints?.Invoke(false, socket.RemoteEndPoint);
                socket.Close();
                SocketClients.Remove(socket);
            }
            /// <summary>
            /// 释放所有套间字
            /// </summary>
            public void Dispose()
            {
                try
                {
                    SocketS.Close();
                    foreach (Socket socket in SocketClients)
                    {
                        socket.Close();
                    }
                }
                catch { }
            }
            /// <summary>
            /// 析构函数
            /// </summary>
            ~TcpServerHelper()
            {
                Dispose();
            }
        }

        #region 人脸数据解析
        public static string FaceDataProcess(int add_int, int add_length_int, byte[] bytes, int data_start)
        {
            string add_string = string.Empty;
            int start = add_int - data_start;
            byte[] data_byte = new byte[add_length_int * 2];
            for (int n = 0; n < add_length_int; n++)
            {
                data_byte[add_length_int * 2 - n * 2 - 1] = bytes[2 * n + 8];
                data_byte[add_length_int * 2 - n * 2 - 2] = bytes[2 * n + 7];
            }

            if (start > 0)
            {
                for (int m = 0; m < start; m++)
                {
                    add_string += "0000000000000000";
                }
                add_string += string.Join("", data_byte.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')));
            }
            else
            {
                add_string = string.Join("", data_byte.Select(b => Convert.ToString(b, 2).PadLeft(8, '0')));
            }
            string floor_data = GetPhysicalFloor(add_string);
            return floor_data;
        }
        #endregion

        #region 解析物理楼层
        public static string GetPhysicalFloor(string data)
        {
            string decimalValue = string.Empty;
            for (int i = 0; i < data.Length; i++)
            {
                if (data.Substring(data.Length - 1 - i, 1) == "1")
                {
                    decimalValue += (i + 1).ToString() + ",";
                }
            }
            return decimalValue.Substring(0, decimalValue.Length - 1);
        }
        #endregion

        #endregion

        #region ttys0 可视对讲
        public List<CemsInfo> cemsInfos;
        public SerialPort myS0SerialPort_1 = new SerialPort();
        public void OpenS0SerialPort(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            try
            {
                SetS0SerialPortConfig(portName, baudRate, parity, dataBits, stopBits);
                myS0SerialPort_1.Open();
            }
            catch (Exception e)
            {
                SmartCommunityLogHelper.Log(e.ToString());
            }
        }

        private Timer SerialPortRecvTimerS0_1;
        private static int byteLength = 40960;
        public byte[] byteSerialPortRecvS0_1 = new byte[byteLength];
        public event EventHandler<SerialPort485_1RecvEventArgs> ReceivedDataEventS0_1;
        private static int pSerialPortRecv_S0_1 = 0;

        public class SerialPort485_1RecvEventArgs : EventArgs
        {
            /// <summary>
            /// 广播 收到的串口数据
            /// </summary>
            public readonly byte[] RecvData_485_1 = new byte[byteLength];

            /// <summary>
            /// 收到数据 的 长度
            /// </summary>
            public readonly int RecvDataLength_485_1;

            /// <summary>
            /// 将 收到的数据 转化成 待广播的数据
            /// </summary>
            public SerialPort485_1RecvEventArgs(byte[] recvData, int recvDataLength)
            {
                recvData.CopyTo(RecvData_485_1, 0);
                RecvDataLength_485_1 = recvDataLength;
            }
        }

        private void SetS0SerialPortConfig(string portName, int baudRate, int parity, int dataBits, int stopBits)
        {
            if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
            {
                portName = $"/dev/{portName}";
            }
            // 串口 参数设置
            myS0SerialPort_1.PortName = portName;
            myS0SerialPort_1.BaudRate = baudRate;
            switch (parity)
            {
                case 0:
                default:
                    myS0SerialPort_1.Parity = Parity.None;
                    break;
                case 1:
                    myS0SerialPort_1.Parity = Parity.Odd;
                    break;
                case 2:
                    myS0SerialPort_1.Parity = Parity.Even;
                    break;
                case 3:
                    myS0SerialPort_1.Parity = Parity.Mark;
                    break;
                case 4:
                    myS0SerialPort_1.Parity = Parity.Space;
                    break;
            }
            myS0SerialPort_1.DataBits = 4 < dataBits && dataBits < 9 ? dataBits : 8;
            switch (stopBits)
            {
                case 0:
                    myS0SerialPort_1.StopBits = StopBits.None;
                    break;
                case 1:
                default:
                    myS0SerialPort_1.StopBits = StopBits.One;
                    break;
                case 2:
                    myS0SerialPort_1.StopBits = StopBits.OnePointFive;
                    break;
                case 3:
                    myS0SerialPort_1.StopBits = StopBits.Two;
                    break;
            }
            //my485SerialPort_1.ReadTimeout = 200;
            myS0SerialPort_1.RtsEnable = true;
            myS0SerialPort_1.DataReceived += new SerialDataReceivedEventHandler(DataReceived_ttyS0);

            // 串口 接收数据处理定时器 参数设置
            SerialPortRecvTimerS0_1 = new System.Timers.Timer();
            SerialPortRecvTimerS0_1.Interval = 100;
            SerialPortRecvTimerS0_1.AutoReset = false;
            SerialPortRecvTimerS0_1.Elapsed += new ElapsedEventHandler(SPRecvTimer_Tick_ttyS0_1);
        }

        private void SPRecvTimer_Tick_ttyS0_1(object sender, EventArgs e)
        {
            byte[] TemporaryData = new byte[byteLength];
            int TemporaryDataLength = 0;

            if (ReceivedDataEventS0_1 != null)
            {
                byteSerialPortRecvS0_1.CopyTo(TemporaryData, 0);
                TemporaryDataLength = pSerialPortRecv_S0_1;

                ReceivedDataEventS0_1.Invoke(this, new SerialPort485_1RecvEventArgs(TemporaryData, TemporaryDataLength));
                // 数据处理完后，将指针指向数据头，等待接收新的数据
                pSerialPortRecv_S0_1 = 0;
            }
        }

        private void DataReceived_ttyS0(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPortRecvTimerS0_1.Stop();
            try
            {
                byte[] ReadBuf = new byte[myS0SerialPort_1.BytesToRead];
                if (pSerialPortRecv_S0_1 > byteLength - ReadBuf.Length)
                {
                    pSerialPortRecv_S0_1 = 0;
                }
                myS0SerialPort_1.Read(ReadBuf, 0, ReadBuf.Length);
                ReadBuf.CopyTo(byteSerialPortRecvS0_1, pSerialPortRecv_S0_1);
                pSerialPortRecv_S0_1 += ReadBuf.Length;
                SerialDataSaveLogHelper.Log(ToHexs(ReadBuf));

                for (int i = 0; i < byteSerialPortRecvS0_1.Length; i++)
                {
                    if (byteSerialPortRecvS0_1[i] == 0xA5 && byteSerialPortRecvS0_1[i + 1] == 0x5A && byteSerialPortRecvS0_1[i + 2] == 0x01 && byteSerialPortRecvS0_1[i + 3] == 0x07)
                    {
                        byte[] buffer = new byte[7];
                        for (int j = 0; j < 7; j++)
                        {
                            buffer[j] = byteSerialPortRecvS0_1[i + 2 + j];
                        }
                        byte[] crc = Crc18(buffer);
                        if (crc[0] == byteSerialPortRecvS0_1[i + 10] && crc[1] == byteSerialPortRecvS0_1[i + 9])
                        {
                            Array.Clear(byteSerialPortRecvS0_1, i, 11);
                            int type = buffer[3];
                            //外呼上行
                            if (type == 3)
                            {
                                //楼层
                                int floor = buffer[5];
                                //实际楼层
                                int act_floor = GetIntercomFloor(floor);
                                //房号
                                int room_id = buffer[6];
                                if (room_id == 1 || room_id == 2)
                                {
                                    //02户，外呼上行前门；01户,外呼上行后门
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    //01号电梯发送 
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.OutBoundType = room_id == 2 ? 1 : 4;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundDFloor = "0";
                                    cEMS_Cmd.DeviceId = 1;
                                    cEMS_Cmd.SendTime = DateTime.Now.AddSeconds(IndoorOutbound);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                    //02号电梯发送
                                    cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.OutBoundType = room_id == 2 ? 1 : 4;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundDFloor = "0";
                                    cEMS_Cmd.DeviceId = 2;
                                    cEMS_Cmd.SendTime = DateTime.Now.AddSeconds(IndoorOutbound);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                }
                                else if (room_id == 3)//03户,外呼上行前门
                                {
                                    //03号电梯发送
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.OutBoundType = 1;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundDFloor = "0";
                                    cEMS_Cmd.DeviceId = 3;
                                    cEMS_Cmd.SendTime = DateTime.Now.AddSeconds(IndoorOutbound);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                }
                            }
                            //下行外呼
                            else if (type == 4)
                            {
                                //楼层
                                int floor = buffer[5];
                                //实际楼层
                                int act_floor = GetIntercomFloor(floor);
                                //房号
                                int room_id = buffer[6];
                                if (room_id == 1 || room_id == 2)//02户，外呼下行后门；01户,外呼下行前门
                                {
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    //01号电梯发送
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.OutBoundType = room_id == 2 ? 2 : 5;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundDFloor = "0";
                                    cEMS_Cmd.DeviceId = 1;
                                    cEMS_Cmd.SendTime = DateTime.Now.AddSeconds(IndoorOutbound);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                    //02号电梯发送
                                    cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.OutBoundType = room_id == 2 ? 2 : 5;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundDFloor = "0";
                                    cEMS_Cmd.DeviceId = 2;
                                    cEMS_Cmd.SendTime = DateTime.Now.AddSeconds(IndoorOutbound);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                }
                                else if (room_id == 3)//03户
                                {
                                    //03号电梯发送
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.OutBoundType = 2;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundDFloor = "0";
                                    cEMS_Cmd.DeviceId = 3;
                                    cEMS_Cmd.SendTime = DateTime.Now.AddSeconds(IndoorOutbound);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                }
                            }
                            //授权
                            else if (type == 5)
                            {
                                //内呼楼层
                                int floor = buffer[5];
                                //内呼实际楼层
                                int act_floor = GetIntercomFloor(floor);
                                //房号
                                int room_id = buffer[6];
                                if (room_id == 1 || room_id == 2)//02户，内呼授权后门；01户,内呼授权前门
                                {
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    //01号电梯发送
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundType = 0;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundType = room_id == 2 ? 0 : 3;
                                    cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.DeviceId = 1;
                                    cEMS_Cmd.IsAuthorize = 1;
                                    cEMS_Cmd.AuthorizeType = 3;
                                    SendInbound(cEMS_Cmd);

                                    //02号电梯发送
                                    cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundType = 0;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundType = room_id == 2 ? 0 : 3;
                                    cEMS_Cmd.IsAuthorize = 1;
                                    cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.DeviceId = 2;
                                    cEMS_Cmd.AuthorizeType = 3;
                                    SendInbound(cEMS_Cmd);
                                }
                                else if (room_id == 3)//03户
                                {
                                    //03号电梯发送
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundType = 0;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.InBoundType = 0;
                                    cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.DeviceId = 3;
                                    cEMS_Cmd.IsAuthorize = 1;
                                    cEMS_Cmd.AuthorizeType = 3;
                                    SendInbound(cEMS_Cmd);
                                }
                            }
                            //管理机授权访客梯控、室内机开锁、刷卡开锁、人脸识别开锁
                            else if (type == 2 || type == 6 || type == 8 || type == 9)
                            {
                                //外呼实际楼层
                                int wh_act_floor = GetIntercomFloor(buffer[2]);
                                //内呼实际楼层
                                int act_floor = GetIntercomFloor(buffer[5]);
                                //房号
                                int room_id = buffer[6];
                                if (room_id == 1 || room_id == 2)//02户，后门；01户,前门
                                {
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    //01号电梯发送后门
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundType = room_id == 2 ? 1 : 4;
                                    cEMS_Cmd.InBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundDFloor = wh_act_floor.ToString();
                                    if (wh_act_floor == -1 || wh_act_floor == 1)
                                    {
                                        if (type != 2)
                                        {
                                            cEMS_Cmd.InBoundPFloor = 0;
                                            cEMS_Cmd.InBoundDFloor = "0";
                                        }
                                        else
                                        {
                                            cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                            cEMS_Cmd.InBoundPFloor = 0;
                                        }
                                    }
                                    else
                                    {
                                        cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                        cEMS_Cmd.InBoundPFloor = 0;
                                    }

                                    cEMS_Cmd.InBoundType = room_id == 2 ? 0 : 3;
                                    cEMS_Cmd.DeviceId = 1;
                                    cEMS_Cmd.AuthorizeType = 2;
                                    cEMS_Cmd.SendTime = wh_act_floor == -1 ? DateTime.Now.AddSeconds(MachineOutbound) : DateTime.Now.AddSeconds(OutboundInterval);
                                    cEMS_Cmds.Add(cEMS_Cmd);


                                    cEMS_Cmd = new CEMS_Cmd();
                                    if (wh_act_floor == -1 || wh_act_floor == 1)
                                    {
                                        if (type != 2)
                                        {
                                            cEMS_Cmd.InBoundPFloor = 0;
                                            cEMS_Cmd.InBoundDFloor = "0";
                                        }
                                        else
                                        {
                                            cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                            cEMS_Cmd.InBoundPFloor = 0;
                                        }
                                    }
                                    else
                                    {
                                        cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                        cEMS_Cmd.InBoundPFloor = 0;
                                    }
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundType = room_id == 2 ? 1 : 4;
                                    cEMS_Cmd.OutBoundDFloor = wh_act_floor.ToString();
                                    cEMS_Cmd.InBoundType = room_id == 2 ? 0 : 3;
                                    cEMS_Cmd.DeviceId = 2;
                                    cEMS_Cmd.AuthorizeType = 2;
                                    cEMS_Cmd.SendTime = wh_act_floor == -1 ? DateTime.Now.AddSeconds(MachineOutbound) : DateTime.Now.AddSeconds(OutboundInterval);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                }
                                else if (room_id == 3)//03户
                                {
                                    //03号电梯发送
                                    CEMS_Cmd cEMS_Cmd = new CEMS_Cmd();
                                    cEMS_Cmd.OutBoundPFloor = 0;
                                    cEMS_Cmd.OutBoundType = 1;
                                    cEMS_Cmd.OutBoundDFloor = wh_act_floor.ToString();
                                    cEMS_Cmd.InBoundType = 0;
                                    cEMS_Cmd.InBoundDFloor = act_floor.ToString();
                                    cEMS_Cmd.DeviceId = 3;
                                    cEMS_Cmd.AuthorizeType = 2;
                                    cEMS_Cmd.SendTime = wh_act_floor == -1 ? DateTime.Now.AddSeconds(MachineOutbound) : DateTime.Now.AddSeconds(OutboundInterval);
                                    cEMS_Cmds.Add(cEMS_Cmd);
                                }
                            }
                            //查询状态
                            else if (type == 7)
                            {
                                byte[] status = GetEleState();
                                byte[] data = new byte[12];
                                data[0] = 0x00;
                                data[1] = 0x0C;
                                data[2] = 0x01;
                                data[3] = status[0];
                                data[4] = status[1];
                                data[5] = status[2];
                                data[6] = status[3];
                                data[7] = status[4];
                                data[8] = status[5];
                                data[9] = 0x99;
                                data[10] = 0x99;
                                data[11] = 0x99;

                                byte[] crcdata = Crc18(data);
                                byte[] data_crc = new byte[2];
                                data_crc[0] = crcdata[1];
                                data_crc[1] = crcdata[0];

                                string cmd = "A5 5A " + ToHexStrFromByte(data) + " " + ToHexStrFromByte(data_crc);
                                //string cmd = "A5 5A 00 0C 01 01 05 02 01 03 00 99 99 99 DB 3C";
                                WaitInBound(200);
                                bool result = ttySendMsg(cmd);
                                SmartCommunityLogHelper.Log("状态回复" + cmd + "结果" + result.ToString());

                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {

            }
            SerialPortRecvTimerS0_1.Start();
        }

        public static string ToHexStrFromByte(byte[] byteDatas)
        {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < byteDatas.Length; i++)
            {
                builder.Append(string.Format("{0:X2} ", byteDatas[i]));
            }
            return builder.ToString().Trim();

        }
        #endregion

        // byte[]转十进制
        public static int ByteToInt(byte[] byteArray)
        {

            int decimalValue = 0;
            for (int i = 0; i < byteArray.Length; i++)
            {
                decimalValue += byteArray[i] << 8 * (byteArray.Length - 1 - i);
            }
            return decimalValue;
        }

        // byte转字符串
        public static string ToHexs(byte[] data)
        {
            if (data.Length <= 0) return "";
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < data.Length; i++)
            {
                sb.Append(data[i].ToString("X2") + " ");
            }
            string str = sb.ToString();
            return str;
        }

        // CRC校验
        public byte[] Crc18(byte[] buffer, int start = 0, int len = 0)
        {
            if (buffer == null || buffer.Length == 0) return null;
            if (start < 0) return null;
            if (len == 0) len = buffer.Length - start;
            int length = start + len;
            if (length > buffer.Length) return null;
            ushort crc = 0xFFFF;// Initial value
            for (int i = start; i < length; i++)
            {
                crc ^= buffer[i];
                for (int j = 0; j < 8; j++)
                {
                    if ((crc & 1) > 0)
                        crc = (ushort)(crc >> 1 ^ 0xA001);// 0xA001 = reverse 0x8005
                    else
                        crc = (ushort)(crc >> 1);
                }
            }
            byte[] ret = BitConverter.GetBytes(crc);
            Array.Reverse(ret);
            return ret;
        }

        // 16进制转ASCII
        public static string HexStringToASCII(byte[] bt)
        {
            string lin = "";
            for (int i = 0; i < bt.Length; i++)
            {
                lin = lin + bt[i] + " ";
            }


            string[] ss = lin.Trim().Split(new char[] { ' ' });
            char[] c = new char[ss.Length];
            int a;
            for (int i = 0; i < c.Length; i++)
            {
                a = Convert.ToInt32(ss[i]);
                c[i] = Convert.ToChar(a);
            }

            string b = new string(c);
            return b;
        }

        //楼层十六进制转十进制
        public int GetIntercomFloor(int floor)
        {
            int act_floor = 0;
            if (floor > 245)
            {
                act_floor = floor - 256;
            }
            else
            {
                act_floor = floor;
            }
            return act_floor;
        }

        //定时任务，发送命令队列
        public void CmdListSend()
        {
            try
            {
                Task task = new Task(async () =>
                {
                    if (token.IsCancellationRequested)
                    {
                        return;
                    }
                    resetEvent.WaitOne();
                    //do something
                    DateTime startTime = DateTime.Now;
                    while (true)
                    {
                        try
                        {
                            TimeSpan secondSpan = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
                            if (secondSpan.TotalMilliseconds > 1000)
                            {
                                //延时发送外呼
                                try
                                {
                                    if (cEMS_Cmds != null && cEMS_Cmds.Count > 0)
                                    {
                                        foreach (var item in cEMS_Cmds)
                                        {
                                            try
                                            {
                                                if (item.SendTime <= DateTime.Now)
                                                {
                                                    //发送外呼
                                                    bool result = SendOutbound(item);
                                                    SmartCommunityLogHelper.Log("外呼" + JsonConvert.SerializeObject(item));
                                                    //发送内呼授权
                                                    if (result)
                                                    {
                                                        if (item.InBoundDFloor == "0" && item.InBoundPFloor == 0)
                                                        {
                                                            cEMS_Cmds.Remove(item);
                                                        }
                                                        else
                                                        {
                                                            Wait(200);
                                                            //发送内呼
                                                            bool nh_result = SendInbound(item);
                                                            if (nh_result)
                                                            {
                                                                cEMS_Cmds.Remove(item);
                                                            }
                                                            Wait(200);
                                                        }
                                                    }
                                                }
                                            }
                                            catch
                                            {

                                            }
                                        }
                                    }
                                }
                                catch
                                {

                                }

                                //人脸面板连接状态
                                try
                                {
                                    if (face_status != null && face_status.Count > 0)
                                    {
                                        foreach (KeyValuePair<int, DateTime> kvp in face_status)
                                        {
                                            try
                                            {
                                                TimeSpan secondSpan1 = new TimeSpan(DateTime.Now.Ticks - kvp.Value.Ticks);
                                                if (secondSpan1.TotalSeconds > 180)
                                                {
                                                    //启用检查心跳
                                                    if (HeartCheck == 1)
                                                    {
                                                        int deviceid = kvp.Key;
                                                        ElevatorState elevatorState = new ElevatorState();
                                                        if (elevators_state.TryGetValue(deviceid, out elevatorState))
                                                        {
                                                            //如果设备进入梯控，超时未收到数据，退出梯控
                                                            if (elevatorState.Tk == 1)
                                                            {
                                                                SendExitControl(deviceid);
                                                                Wait(200);
                                                            }
                                                        }
                                                    }
                                                }
                                            }
                                            catch { }
                                        }
                                    }
                                }
                                catch
                                {

                                }
                            }
                        }
                        catch
                        {

                        }
                    }
                }, token);
                task.Start();
            }
            catch (Exception e)
            {
            }
        }

        public void CmdListClear()
        {
            try
            {
                Task task = new Task(async () =>
                {
                    if (clear_token.IsCancellationRequested)
                    {
                        return;
                    }
                    clear_resetEvent.WaitOne();
                    //do something
                    DateTime startTime = DateTime.Now;
                    while (true)
                    {
                        try
                        {
                            TimeSpan secondSpan = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
                            if (secondSpan.TotalMilliseconds > 1000)
                            {
                                //授权到时间清除
                                try
                                {
                                    if (GlobalVariables.SignalPointClearList != null && GlobalVariables.SignalPointClearList.Count > 0)
                                    {
                                        foreach (var item in GlobalVariables.SignalPointClearList)
                                        {
                                            try
                                            {
                                                TimeSpan secondSpan1 = new TimeSpan(DateTime.Now.Ticks - item.ClearTime.Ticks);
                                                if (item.AuthorizeType == 1 && secondSpan1.TotalSeconds > CarInOutbound)
                                                {
                                                    bool success = IGTCPServerMessageProcess.ProcessPointClear(item);
                                                    Wait(200);
                                                    if (success)
                                                    {
                                                        GlobalVariables.SignalPointClearList.Remove(item);
                                                        SmartCommunityLogHelper.Log("清除授权点位" + JsonConvert.SerializeObject(item));
                                                    }
                                                }
                                                else if (item.AuthorizeType == 2 && secondSpan1.TotalSeconds > MachineAuthorize)
                                                {
                                                    bool success = IGTCPServerMessageProcess.ProcessPointClear(item);
                                                    Wait(200);
                                                    if (success)
                                                    {
                                                        GlobalVariables.SignalPointClearList.Remove(item);
                                                        SmartCommunityLogHelper.Log("清除授权点位" + JsonConvert.SerializeObject(item));
                                                    }
                                                }
                                                else if (item.AuthorizeType == 3 && secondSpan1.TotalSeconds > IndoorAuthorize)
                                                {
                                                    bool success = IGTCPServerMessageProcess.ProcessPointClear(item);
                                                    Wait(200);
                                                    if (success)
                                                    {
                                                        GlobalVariables.SignalPointClearList.Remove(item);
                                                        SmartCommunityLogHelper.Log("清除授权点位" + JsonConvert.SerializeObject(item));
                                                    }
                                                }

                                            }
                                            catch
                                            {

                                            }
                                        }
                                    }
                                }
                                catch
                                {

                                }

                                //管理卡到时间清除
                                try
                                {
                                    if (manager_card != null && manager_card.Count > 0)
                                    {
                                        foreach (KeyValuePair<int, DateTime> kvp in manager_card)
                                        {
                                            try
                                            {
                                                TimeSpan secondSpan1 = new TimeSpan(DateTime.Now.Ticks - kvp.Value.Ticks);
                                                if (secondSpan1.TotalSeconds > CarInOutbound)
                                                {
                                                    IGTCPServerMessageProcess.SmartEnableLiftControl(kvp.Key);
                                                    manager_card.Remove(kvp.Key);
                                                    Wait(200);
                                                }
                                            }
                                            catch { }
                                        }
                                    }
                                }
                                catch
                                {

                                }
                            }
                        }
                        catch
                        {

                        }
                    }
                }, clear_token);
                task.Start();
            }
            catch (Exception e)
            {
            }
        }

        public bool Wait(int second)
        {
            try
            {
                DateTime startTime = DateTime.Now;
                while (true)
                {
                    TimeSpan secondSpan = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
                    if (secondSpan.TotalMilliseconds > second)
                    {
                        break;
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        public static bool WaitInBound(int second)
        {
            try
            {
                DateTime startTime = DateTime.Now;
                while (true)
                {
                    TimeSpan secondSpan = new TimeSpan(DateTime.Now.Ticks - startTime.Ticks);
                    if (secondSpan.TotalMilliseconds > second)
                    {
                        break;
                    }
                }
                return true;
            }
            catch
            {
                return false;
            }
        }

        //发送外呼
        public bool SendOutbound(CEMS_Cmd cEMS_Cmd)
        {
            var item = GlobalVariables.DeviceList.Find(t =>
            {
                if (t.NO == cEMS_Cmd.DeviceId) return true;
                else return false;
            });
            if (item != null)
            {
                SignalPointDA da = new SignalPointDA();
                SignalPoint point = da.GetSignalPointPFloorData(cEMS_Cmd.OutBoundType, cEMS_Cmd.OutBoundDFloor, cEMS_Cmd.DeviceId.ToString());

                return IGTCPServerMessageProcess.SmartProcessOutCall(point, item.DeviceIP);
            }
            else
            {
                return true;
            }
        }

        //发送内呼
        public static bool SendInbound(CEMS_Cmd cEMS_Cmd)
        {
            var item = GlobalVariables.DeviceList.Find(t =>
            {
                if (t.NO == cEMS_Cmd.DeviceId) return true;
                else return false;
            });
            if (item != null)
            {
                SignalPointDA signalPointDA = new SignalPointDA();
                List<SignalPoint> list = new List<SignalPoint>();
                if (!string.IsNullOrEmpty(cEMS_Cmd.InBoundPFloorIds))
                {
                    //内呼物理楼层
                    list = signalPointDA.GetSignalPFloorPointListData(cEMS_Cmd.InBoundType, cEMS_Cmd.InBoundPFloorIds, cEMS_Cmd.DeviceId.ToString());
                }
                else
                {
                    //内呼显示楼层
                    list = signalPointDA.GetSignalDFloorPointListData(cEMS_Cmd.InBoundType, cEMS_Cmd.InBoundDFloor, cEMS_Cmd.DeviceId.ToString());
                }
                return IGTCPServerMessageProcess.SmartInCallMultiFloor(list, cEMS_Cmd.IsAuthorize, item.DeviceIP, cEMS_Cmd.AuthorizeType);
            }
            else
            {
                return true;
            }
        }

        //发送退出梯控
        public bool SendExitControl(int deviceid)
        {
            return IGTCPServerMessageProcess.SmartDisableLiftControl(deviceid);
        }

        //获取电梯状态
        public byte[] GetEleState()
        {
            byte[] bytes = new byte[6];
            for (int i = 1; i < 4; i++)
            {
                ElevatorState elevatorState = new ElevatorState();
                if (elevators_state.TryGetValue(i, out elevatorState))
                {
                    bytes[2 * i - 2] = (byte)((elevatorState.direction == 0 || elevatorState.direction == 3) ? elevatorState.direction_old == 0 ? 1 : elevatorState.direction_old : elevatorState.direction & 0xFF);
                    int floor = GetDisplayfloor(elevatorState.dfloor);
                    bytes[2 * i - 1] = (byte)(floor & 0xFF);
                }
                else
                {
                    bytes[2 * i - 2] = 0x03;
                    bytes[2 * i - 1] = 0x00;
                }
            }
            return bytes;
        }

        public int GetDisplayfloor(string displayfloor)
        {
            int floor = Convert.ToInt32(displayfloor);
            if (floor < 0)
            {
                floor += 256;
            }
            return floor;
        }


        public bool ttySendMsg(string data)
        {
            try
            {
                myS0SerialPort_1.Write(ToBytesSendDate(data), 0, ToBytesSendDate(data).Length);
                return true;
            }
            catch (Exception e)
            {
                return false;
            }
        }

        public byte[] ToBytesSendDate(string str)
        {
            List<byte> result = new List<byte>();
            if (str.Contains(" "))
            {
                string[] strs = str.Trim().Split(' ');
                foreach (string s in strs)
                {
                    result.Add(Convert.ToByte(s.Trim(), 16));
                }
            }
            else
            {
                result.Add(Convert.ToByte(str, 16));
            }
            return result.ToArray();
        }

    }
}
